<?php

/**
 * PDF Page
 *
 * @package    Zend_Pdf
 * @copyright  Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
class Evebit_Pdf_Page extends Zend_Pdf_Page {
	public $totalHeight = 0;
	/**
	 * Left align text block.
	 */
	const ALIGN_LEFT = 'left';
	
	/**
	 * Right align text block.
	 */
	const ALIGN_RIGHT = 'right';
	
	/**
	 * Center text block.
	 */
	const ALIGN_CENTER = 'center';
	
	/**
	 * Justify text in block.
	 */
	const ALIGN_JUSTIFY = 'justify';
	
	public $startPoint = array('x'=>'50', 'y'=>'30');
	/**
	 * Get height of one or more line(s) in with current font and font size.
	 *
	 * @param int $lines number of lines
	 * @param int $extraSpacing spaceing between lines
	 * @return int line height
	 */
	public function getLineHeight($lines = 1, $extraSpacing = 1) {
		return $lines * $this->_fontSize * $this->_font->getLineHeight () / $this->_font->getUnitsPerEm () + $extraSpacing;
	}
	/**
	 * Calculate the width for the given string.
	 *
	 * @param string $string
	 * @param string $charset charset of the string
	 * @return int width of string
	 */
	public function widthForString($string, $charset = 'ISO-8859-1') {
		$drawingString = iconv ( $charset, 'UTF-16BE//IGNORE', $string );
		$characters = array ();
		for($i = 0; $i < strlen ( $drawingString ); $i ++) {
			$characters [] = (ord ( $drawingString [$i ++] ) << 8) | ord ( $drawingString [$i] );
		}
		
		$glyphs = $this->_font->glyphNumbersForCharacters ( $characters );
		$widths = $this->_font->widthsForGlyphs ( $glyphs );
		
		$stringWidth = (array_sum ( $widths ) / $this->_font->getUnitsPerEm ()) * $this->_fontSize;
		return $stringWidth;
	}
	
	/**
	 * Helper method to wrap text to lines. The wrapping is done at whitespace if the text gets longer
	 * as $width.
	 * 
	 * @param string $text the text to wrap
	 * @param int $width
	 * @param int $initial_line_offset x offset for start position in first line
	 * @return array array with lines as array('words' => array(...), 'word_lengths' => array(...), 'total_length' => <int>)
	 */
	public function wrapText($text, $width = null, $initial_line_offset = 0) {
		$width = $width?$width:$this->getWidth()-2*$this->startPoint['x'];
		$lines = array ();
		$line_init = array ('words' => array (), 'word_lengths' => array (), 'total_length' => 0, 'line_height' => $this->getLineHeight (), 'width' => $width );
		$line = $line_init;
		$line ['total_length'] = $initial_line_offset;
		
		$text = preg_split ( '%[\n\r ]+%', $text, - 1, PREG_SPLIT_NO_EMPTY );
		$space_length = $this->widthForString ( ' ' );
		foreach ( $text as $word ) {
			$word_length = $this->widthForString ( $word );
			if ($word_length > $width) {
				if ($line ['words']) {
					$lines [] = $line;
				}
				$lines [] = array ('words' => array ($word ), 'word_lengths' => array ($word_length ), 'total_length' => array ($word_length ) );
				$line = $line_init;
				continue;
			}
			if ($line ['total_length'] + $word_length > $width) {
				$line ['total_length'] -= $space_length;
				$lines [] = $line;
				$line = $line_init;
			}
			$line ['words'] [] = $word;
			$line ['word_lengths'] [] = $word_length;
			$line ['total_length'] += $word_length + $space_length;
		}
		if ($line) {
			$line ['total_length'] -= $space_length;
			$lines [] = $line;
		}
		
		return $lines;
	}
	
	public function checkHeight($lines, $option = null) {
		$height = $this->getHeight()-$this->totalHeight-$this->startPoint['y'];
		$height = $option?$height-$option['distance']:$height;
		$count = $height/$lines[0]['line_height'];
		if ($count>count($lines)){
			$result['current'] = $lines;
			$result['next'] = null;
		} elseif ($count<1){
			$result['current'] = null;
			$result['next'] = $lines;
		} else {
			$key = floor($count);
			$result['current'] = array_slice($lines, 0, $key);
			$result['next'] = array_slice($lines, $key);
		}
		
		return $result;
	}
	/**
	 * Draw a text in a block with a fixed width and an optional fixed height. The text can be left or right
	 * aligned, centered of justified. If height is given, but the text would be longer an exception is thrown.
	 *
	 * This method may also be called as drawTextBlock($text, $width). The block is than drawn to the current
	 * cursor position.
	 *
	 * @param string $text
	 * @param int $x x position
	 * @param int $y y position
	 * @param int $width block width
	 * @param int|null $height optional height to check for
	 * @param string $align one of: self::ALIGN_LEFT, self::ALIGN_RIGHT, self::ALIGN_CENTER, self::ALIGN_JUSTIFY
	 * @throws Zend_Pdf_Exception
	 */
	public function drawTextBlock($lines, $options = null) {
		
		$width = $lines[0] ['width'];
		$line_height = $lines[0] ['line_height'];

		$y = $this->getHeight()-$this->totalHeight-$this->startPoint['y'];
		$x = $this->startPoint['x'];
		$align = self::ALIGN_LEFT;
		if ($options){
			$align = array_key_exists('align', $options)?$options['align']:$align;
			if (array_key_exists('distance', $options)){
				$y = $y-$options['distance'];
				$this->totalHeight += $options['distance'];
			};
			$x = array_key_exists('x', $options)?$x+$options['x']:$x;
		}
		
		//$this->totalHeight += $y;
		foreach ( $lines as $k => $line ) {
			$this->totalHeight += $line ['line_height'];
			switch ($align) {
				case self::ALIGN_JUSTIFY :
					if (count ( $line ['words'] ) < 2 || $k == count ( $lines ) - 1) {
						$this->drawText ( implode ( ' ', $line ['words'] ), $x, $y );
						break;
					}
					$space_width = ($width - array_sum ( $line ['word_lengths'] )) / (count ( $line ['words'] ) - 1);
					$pos = $x;
					foreach ( $line ['words'] as $k => $word ) {
						$this->drawText ( $word, $pos, $y );
						$pos += $line ['word_lengths'] [$k] + $space_width;
					}
					break;
				case self::ALIGN_CENTER :
					$this->drawText ( implode ( ' ', $line ['words'] ), $x + ($width - $line ['total_length']) / 2, $y );
					break;
				case self::ALIGN_RIGHT :
					$this->drawText ( implode ( ' ', $line ['words'] ), $x + $width - $line ['total_length'], $y );
					break;
				case self::ALIGN_LEFT :
				default :
					$this->drawText ( implode ( ' ', $line ['words'] ), $x, $y );
					break;
			}
			$y -= $line_height;
		}
	}
}

